package com.mai4j.maiadmin.support.web;

import io.github.mngsk.devicedetector.DeviceDetector;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信公众号请关注: 开源螺丝钉
 * <br>
 * 码云请关注: <a href="https://gitee.com/xiyoufang">https://gitee.com/xiyoufang</a>
 * <br>
 * 哔哩哔哩请关注: <a href="https://space.bilibili.com/438927834">https://space.bilibili.com/438927834</a>
 *
 * @author xiyoufang
 */
public class Client {

    private final static DeviceDetector DD = new DeviceDetector.DeviceDetectorBuilder().build();

    private static final ThreadLocal<ClientInfo> local = new ThreadLocal<>();

    /**
     * 创建客户端信息
     */
    static void create(HttpServletRequest request) {
        Map<String, String> cookies = new HashMap<>();
        if (request.getCookies() != null) {
            for (Cookie cookie : request.getCookies()) cookies.put(cookie.getName(), cookie.getValue());
        }
        String userAgent = StringUtils.defaultIfBlank(request.getHeader("User-Agent"), "unknown");
        local.set(new ClientInfo()
                .setDevice(DD.detect(userAgent))
                .setUserAgent(userAgent)
                .setAcceptLanguage(request.getHeader("Accept-Language"))
                .setIp(request.getRemoteAddr()) // 如果通过网关调用获取的是网关IP
                .setForwardedIp(getForwardedIp(request))
                .setCookies(cookies));
    }

    /**
     * 移除客户端信息
     */
    static void remove() {
        local.remove();
    }

    /**
     * 获取 x-forwarded-for ip
     *
     * @param request request
     * @return forwarded ip
     */
    private static String getForwardedIp(HttpServletRequest request) {
        // 如果使用反向代理，才使用下面代码获取IP，否则可以通过修改x-forwarded-for header 伪造IP
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 获取访问的客户端信息 ClientInfo
     *
     * @return ClientInfo
     */
    public static ClientInfo get() {
        return local.get();
    }
}
